<?php
class style 
{
	private $cache = 'cache/';
	private $compress = true;
	private $file;
	private $filename;
	private $isLocal;
	private $filemodtime;
	public $cachefile;
	private $isCache = true;
	private $content;
	public $browser;
	private $md5;
	public $path = false;
	public $changed = false;
	
	public function __construct($compress = true, $isCache = true)
	{
		$this->compress = $compress;
		$this->isCache = $isCache;
		$this->browser = self::getBrowser();
		$this->browser = $this->browser['name'];

	}
	
	public function compressCSS($file)
	{
		$fData = explode("/", $file);	
		$fileName = end($fData);
		unset($fData[count($fData) - 1]);
		array_pop($fData);
		$this->path = preg_replace('/^\./' , '', implode("/", $fData) . "/");
		$this->md5 = md5_file($file);
		$this->file = $file;
		$this->filename = (strpos($file, "/")) ? substr(strrchr($this->file, '/'), 1) : $file;
		$this->isLocal = self::isLocal($this->file);

		if($this->getCache())
			return $this->content;
			
		if($this->isLocal && file_exists($this->file))
			$this->content = file_get_contents($this->file);
		else
			$this->content = self::_getContent($this->file);
		
		$this->filterCSS();
		
		$this->updateCache();
			
		return $this->content;
	}
	
	public function compressCSSCode($code, $name)
	{
		$this->file = false;
		$this->filename = $name;
		$this->md5 = md5($code);
		$this->isLocal = true;
		
		if($this->getCache())
			return $this->content;			

		$this->content = $code;
		
		$this->filterCSS();
		
		$this->updateCache();
			
		return $this->content;		
	}
	
	private function filterCSS()
	{
		if($this->browser != 'webkit')
		{
			$pattern[] = '/-webkit-(box-shadow:)([^;]+);/';
			$pattern[] = '/-webkit-(border-radius:)([^;]+);/';
			$pattern[] = '/-webkit-border-([^-]+)-([^-]+)-radius:([^;]+);/';
			$pattern[] = '/-webkit-(transition:)([^;]+);/';
			$pattern[] = '/-webkit-(transform:)([^;]+);/';
			$pattern[] = '/-webkit-(transform-origin:)([^;]+);/';
			$pattern[] = '/-webkit-(gradient)\(([^\,]+),\ ?([^\ ]+) ([^\,]+),\ ?([^\ ]+) ([^\,]+),\ ?from\((.+)\),\ ?to\((.+)\)\)/';
			$pattern[] = '/-webkit-(user-select:)([^;]+);/';
			$pattern[] = '/::(selection)/';
			$pattern[] = '/-webkit-(font-smoothing:)([^;]+);/';
			$pattern[] = '/-webkit-user-drag:([^;]+);/';
			$pattern[] = '/(text-overflow:)([^;]+);/';
			$pattern[] = '/-webkit-/';
			//$pattern[] = '/-webkit-([^;]+);/';
			
			$this->convertGradient();
			//$this->convertBoxShadow();
			
			switch($this->browser)
			{
				case "mozilla":					
					$replacement[] = "-moz-$1$2;";
					$replacement[] = "-moz-$1$2;";
					$replacement[] = "-moz-border-radius-$1$2:$3;";
					$replacement[] = "-moz-$1$2;";
					$replacement[] = "-moz-$1$2;";
					$replacement[] = "-moz-$1$2;";
					$replacement[] = "-moz-$2-$1($4, $7, $8)";
					$replacement[] = "-moz-$1$2;";
					$replacement[] = "::moz-$1";
					$replacement[] = "-moz-$1$2;";
					$replacement[] = "draggable:$1;";
					$replacement[] = "$1$2;";
					$replacement[] = "";
					//$replacement[] = "-moz-$1;";
				break;
				
				case "opera":
					$replacement[] = "$1$2;";
					$replacement[] = "$1$2;";
					$replacement[] = "border-$1-$2-radius:$3;";
					$replacement[] = "-o-$1$2;";
					$replacement[] = "-o-$1$2;";
					$replacement[] = "-o-$1$2;";
					$replacement[] = "";
					$replacement[] = "$1$2;";
					$replacement[] = "::$1";
					$replacement[] = "-o-$1$2;";
					$replacement[] = "draggable:$1;";
					$replacement[] = "-o-$1$2;";
					$replacement[] = "-o-";
					//$replacement[] = "-o-$1;";
					
				break;
				
				default:
				case "msie":
					$this->convertRGBA();
					$replacement[] = "$1$2;";
					$replacement[] = "$1$2;";
					$replacement[] = "border-$1-$2-radius:$3;";
					$replacement[] = "$1$2;";
					$replacement[] = "$1$2;";
					$replacement[] = "$1$2;";
					$replacement[] = "";
					$replacement[] = "$1$2;";
					$replacement[] = "::$1";
					$replacement[] = "$1$2;";
					$replacement[] = "draggable:$1;";
					$replacement[] = "$1$2;";
					$replacement[] = "";
					//$replacement[] = "";
					
					$pattern[] = '/opacity:\ ?0;/';
					$replacement[] = "filter:alpha(opacity=0);";
					$pattern[] = '/opacity:\ ?1;/';
					$replacement[] = 'filter:alpha(opacity=100);';
					$pattern[] = '/opacity:\ ?0?\.([\d]+);/';
					$replacement[] = 'filter:alpha(opacity=${1}0);';
					
				break;
				
			}
			
		}
		
		if($this->compress)
		{
			
			$pattern[] = '/\/\*[^\*]+\*\//';
			$replacement[] = '';
			
			$pattern[] = '/[\t\ ]*\/\/.*\n/';
			$replacement[] = '';
			
			 $pattern[] = '/[\t\n\r]+/';
			 $replacement[] = '';
	
			 $pattern[] = '/[\ ]{2,}/';
			 $replacement[] = '';		
			
		}
		
		 if($this->path)
		 {		
		 	$pattern[] = '/\(..\//';
		 	$replacement[] = '(' . $this->path . '';
		 }
		
		if(isset($pattern) && is_array($pattern) && is_array($replacement))
			$this->content = trim(preg_replace($pattern, $replacement, $this->content));

	}
	
	private function convertGradient()
	{
		if(!preg_match_all('/-webkit-gradient\(.*\)/', $this->content, $matches))
			return false;
		
		//if(!preg_match_all('/-webkit-gradient\(.*color-stop\(.*\).*\)/', $this->content, $matches) or $this->browser != 'mozilla')
		
		$gradients = array();
		
		foreach($matches[0] as $match)
		{
			$g['original'] = $match;
			preg_match('/-webkit-gradient\(([^\,]+),\ ?([^\ ]+) ([^\,]+),\ ?([^\ ]+) ([^\,]+), /', $match, $m);
			list($pp, $g['type'], $g['x1'], $g['x2'], $g['y1'], $g['y2']) = $m;
			$colors = explode("), ", trim(preg_replace("/\)$/", "", str_replace($m[0], "", $match))));
			foreach($colors as $color)
			{
				if(end($colors) != $color)
					$color .= ')';
					
				if(preg_match('/from\((.+)\)/', $color, $m))
					$g['from'] = $m[1];
				elseif(preg_match('/to\((.+)\)/', $color, $m))
					$g['to'] = $m[1];
				elseif(preg_match('/\(([^,]+),(.+)\)$/', $color, $m))
					$g['stops'][] = array("pos" => (float)trim($m[1]), 'color' => trim($m[2]));
			}

			$gradients[] = $g;
		}

		switch($this->browser)
		{
			case "mozilla":
				foreach($gradients as $grad)
				{
					$cstops = '';
					if(isset($grad['stops']) and count($grad['stops']))
					foreach($grad['stops'] as $stop)
						$cstops .= "{$stop['color']} " . ($stop['pos']*100) . "%, ";
					$mozgrad = "-moz-{$grad['type']}-gradient({$grad['x2']}, {$grad['from']}, {$cstops}{$grad['to']})";
					$this->content = str_replace($grad['original'], $mozgrad, $this->content);
				}				
			break;
			
			case "msie":
				foreach($gradients as $grad)
				{
					$msiegrad = "filter:progid:DXImageTransform.Microsoft.gradient(enabled='true', startColorstr=". $this->rgbaToHex($grad['from']) .", endColorstr=". $this->rgbaToHex($grad['to']) . ");";							
					
					$this->content = preg_replace("/(\n.*". preg_quote($grad['original'], "/") . ".*\n)/", "$1{$msiegrad}", $this->content);
				}
			break;
		}
	}
	
	private function convertBoxShadow()
	{
		if(!preg_match_all('/-webkit-box-shadow:\ ?(\d{1,2}\w{0,2})\ (\d{1,5}\w{0,2})\ (\d{1,5}\w{0,2})\ ([^;]+);/', $this->content, $matches, PREG_SET_ORDER) or $this->browser != "msie")
			return false;
		
		if(!is_array($matches) || !count($matches))
			return false;
			
		$pattern = array();
		$replacement = array();	
		foreach($matches as $match)
		{
			$pattern[] = "/" . preg_quote($match[0]) . "/";
			$match[1] =  intval($match[1]);
			$match[2] =  intval($match[2]);
			$match[3] =  intval($match[3]);
			
			$rp = "filter:progid:DXImageTransform.Microsoft.DropShadow(color='" . $this->rgbaToHex($match[4]) . "',offX='{$match[1]}',offY='{$match[2]}');";
			$replacement[] = $rp;
		}
		//__pr($replacement);
		$this->content = preg_replace($pattern, $replacement, $this->content);
	}
	
	private function convertRGBA()
	{
		$pattern = array();
		$replacement = array();
		if(!preg_match_all('/rgba?\(([^,]+),([^,]+),([^,]+),?([^\)]+)?\)/', $this->content, $matches))
		return false;
	
		foreach($matches[0] as $match)
		{
			$match = trim($match);
			$pattern[] = "/" . preg_quote($match) . "/";
			$replacement[] = $this->rgbaToHex($match);
		}
	
		$this->content = preg_replace($pattern, $replacement, $this->content);
	}
	
	private function rgbaToHex($color)
	{
		if(!preg_match('/rgba?\(([^,]+),([^,]+),([^,]+),?([^\)]+)?\)/', $color, $matches))
			return $color;

		@list($t, $r, $g, $b, $a) = $matches;

		$a = (!isset($a)) ? 1 : (float)trim($a);

		$r = trim($r)*$a;
		$g = trim($g)*$a;
		$b = trim($b)*$a;

		return sprintf("#%02x%02x%02x", $r, $g, $b); 
	}
	
	private function updateCache()
	{
		if($this->isCache && $this->isLocal){
			$this->emptyCache("*" . md5($this->file) . ".css");
			file_put_contents($this->cachefile, $this->content);
		}
	}
	
	private function getCache()
	{
		$this->changed = false;
		if($this->isCache && $this->isLocal)
		{
			$c = ($this->compress) ? 'compressed' : 'uncompressed';
			$this->cachefile = $this->cache . "{$this->md5}-{$this->browser}-{$c}-". md5($this->file) . ".css";		
		}
		
		if($this->file && $this->isCache && $this->isLocal && file_exists($this->file))
		{
			$this->filemodtime = filemtime($this->file);			
			if(file_exists($this->cachefile))
			{	
				$this->content = file_get_contents($this->cachefile);
				return true;
			}
		}
		elseif($this->isCache && $this->isLocal)
		{			
			if(file_exists($this->cachefile))
			{	
				$this->content = file_get_contents($this->cachefile);
				return true;
			}
		}
		$this->changed = true;
		return false;
	}
	
	public static function isLocal($file)
	{
		return !preg_match('/http:\/\//', $file);
	}
	
	private function emptyCache($file)
	{
		$match = glob($this->cache . $file);
		if(is_array($match) && count($match))
		foreach($match as $m)
		{
			if(file_exists($m))
				@unlink($m);
		}
	}
	
	public static function _getContent($url)
	{
		$ch = curl_init();

		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HEADER, 0);
		curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

		$string = curl_exec($ch);
		curl_close ($ch);
		
		return $string;
	}
	
  public static function getBrowser()
	{ 
			$userAgent = strtolower($_SERVER['HTTP_USER_AGENT']); 

			// Identify the browser. Check Opera and Safari first in case of spoof. Let Google Chrome be identified as Safari. 
			if (preg_match('/opera/', $userAgent)) { 
			    $name = 'opera'; 
			} 
			elseif (preg_match('/webkit/', $userAgent)) { 
			    $name = 'webkit'; 
			} 
			elseif (preg_match('/msie/', $userAgent)) { 
			    $name = 'msie'; 
			} 
			elseif (preg_match('/mozilla/', $userAgent) && !preg_match('/compatible/', $userAgent)) { 
			    $name = 'mozilla'; 
			} 
			else { 
			    $name = 'unrecognized'; 
			} 

			// What version? 
			if (preg_match('/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/', $userAgent, $matches)) { 
			    $version = $matches[1]; 
			} 
			else { 
			    $version = 'unknown'; 
			} 

			// Running on what platform? 
			if (preg_match('/linux/', $userAgent)) { 
			    $platform = 'linux'; 
			} 
			elseif (preg_match('/macintosh|mac os x/', $userAgent)) { 
			    $platform = 'mac'; 
			} 
			elseif (preg_match('/windows|win32/', $userAgent)) { 
			    $platform = 'windows'; 
			} 
			else { 
			    $platform = 'unrecognized'; 
			} 


			if(preg_match("/Version[\/\s](\d+\.\d+\.?\d*)\ Safari/i", $userAgent, $m))
			{
				$browserName = "Safari";
				$browserVersion = (float)$m[1];
			}
			elseif(preg_match("/Chrome[\/\s](\d+\.\d+\.?\d*)/i", $userAgent, $m))
			{
				$browserName = "Chrome";
				$browserVersion = (float)$m[1];
			}
			elseif(preg_match("/Firefox[\/\s](\d+\.\d+\.?\d*)/i", $userAgent, $m))
			{
				$browserName = "Firefox";
				$browserVersion = (float)$m[1];
			}
			elseif(preg_match("/MSIE (\d+\.\d+);/i", $userAgent, $m))
			{
				$browserName = "MSIE";
				$browserVersion = (float)$m[1];
			}
			elseif(preg_match("/Opera[\/\s]\d+\.\d+\.?\d* .* version[\/\s](\d+\.\d+\.?\d*)/i", $userAgent, $m))
			{
				$browserName = "Opera";
				$browserVersion = (float)$m[1];
			}

			return array( 
			    'name'      => $name, 
			    'version'   => $version, 
			    'platform'  => $platform, 
			    'userAgent' => $userAgent,
			 		'browserName' => (isset($browserName)) ? $browserName :  ('undefined'),
					'browserVersion' => (isset($browserVersion)) ? str_replace(",", ".", $browserVersion) : 0
			); 
   }
	
}	
?>